home *** CD-ROM | disk | FTP | other *** search
- From: decvax!wanginst!perlman
- Subject: ff: fast test formatter (part 2 of 2)
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 3, Issue 52
- Submitted by: decvax!wanginst!perlman
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # ff.c
- # This archive created: Wed Nov 13 19:28:01 1985
- # By: Gary Perlman (Wang Institute, Tyngsboro, MA 01879 USA)
- export PATH; PATH=/bin:/usr/bin:$PATH
- echo shar: "extracting 'ff.c'" '(29326 characters)'
- if test -f 'ff.c'
- then
- echo shar: "will not over-write existing file 'ff.c'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'ff.c'
- X/*COPYRIGHT (c) 1985 Wang Institute, Tyngsboro, MA 01879 USA */
- X/*DISCLAIMER: No guarantees of performance are made. */
- X/*MODULE ff: "fast formatter" "Sun 01 Sep 1985" */
- X/*PGMR ff: "Gary Perlman" "Wang Institute, Tyngsboro, MA 01879 USA" */
- X/*VER $Header: ff.c,v 1.3 85/09/01 21:23:38 perlman Exp $ */
- X/*COMP ff: see makefile */
- X
- X/*MANUAL.TH FF 1 "August 10, 1985" "Wang Institute" "UNIX User's Manual"
- X.\" $Compile: iroff -man.new %f
- X.SH NAME
- Xff \- fast text formatter
- X.SH USAGE
- X.B ff
- X[options] [-] [files]
- X.SH DESCRIPTION
- X.I ff
- Xis a simple text formatter for flexible uniform formatting of
- Xinput files.
- XProgram options are used to control formatting.
- XThis is in contrast to text formatters like
- X.I nroff (1)
- Xthat require special format requests to be part of their input files.
- XBesides avoiding cryptic format requests in text,
- X.I ff
- Xis considerably faster than traditional formatters like
- X.I nroff (1)
- Xand even simple formatters like
- X.I fmt (1).
- X.PP
- XThe most complicated concept with
- X.I ff
- Xis that of a line break.
- XA line break causes an interruption in the filling
- X(evening out of the text lines).
- XLine breaks occur when special characters are seen at the beginnings
- Xof lines, or when all lines are broken.
- XBy default, any non-alphanumeric character will cause a break,
- Xbut this can be controlled with the
- X.B -B
- Xoption.
- XA blank line always causes a break.
- X*/
- X
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <strings.h>
- X
- Xtypedef int Status;
- X#define SUCCESS ((Status) 0)
- X#define FAILURE ((Status) 1)
- Xtypedef int Boole;
- X#define TRUE ((Boole) 1)
- X#define FALSE ((Boole) 0)
- X
- X#define TAB '\t'
- X#define EOL '\n'
- X#define FF '\f'
- X#define EOS '\0'
- X#define SP ' '
- X#define MAXLEN 128 /* max length of lines */
- X#define MAXLINES 200 /* max # lines on pages */
- X
- X/* Alphabetical listing of this file's functions */
- Xvoid beginline (); /* process text at the beginning of lines */
- Xvoid beginpage (); /* handle pagination at page breaks */
- XStatus dobreak (); /* handle broken lines, if appropriate */
- Xvoid dofill (); /* do the text filling */
- Xchar *dotab (); /* return expanded tabs in line */
- Xvoid endpage (); /* handle pagination at page ends */
- Xchar *expand (); /* expand strings in three part titles */
- XStatus ff (); /* main formatting routine */
- Xint initial (); /* set options and check consistency */
- Xchar *itoa (); /* convert integer to ascii format, with padding */
- Xvoid dojustify (); /* even out (justify) the right margin of filled lines */
- Xchar *preprocess ();/* handle blank trimming and titling */
- Xvoid println (); /* print a line, watching for page boundaries */
- Xvoid repeat (); /* repeatedly print a character */
- XStatus setint (); /* check type & convert a string to an integer */
- Xchar *threepart (); /* build three part titles */
- Xvoid usage (); /* print usage summary */
- X
- X/* GLOBALS */
- Xchar *Argv0; /* will be name of program */
- Xint Curpos; /* current position on output line */
- Xchar *Filename; /* current input file name */
- XBoole Filling; /* is text being filled right now */
- Xchar Justbuf[MAXLEN]; /* buffer for justified text */
- Xint Justpos; /* current position in justification buffer */
- Xint Outline; /* output line number */
- Xint Pageline; /* line number on current output page */
- Xint Pagenum; /* current page number */
- X
- X/* Default values of options */
- X#define MAXTAB 20 /* max # of tab stops */
- X#define FOOTSIZE 5 /* default footer size */
- X#define HEADSIZE 5 /* default header size */
- X#define NUMWIDTH 4 /* default width of line numbers */
- X#define PAGESIZE 66 /* default length of page */
- X#define WIDTH 72 /* default width of page */
- X#define PAGENUM '%' /* expands to page number in titles */
- X#define FILENAME '*' /* expands to file name in title */
- X#define HEADER "|File: *||Page: %|" /* default page header */
- X
- X/*MANUAL.SH OPTIONS
- XThere are many, many options to allow control of
- Xindentation, line width, line spacing, filling,
- Xpagination with headers and footers,
- Xline numbering, right justification,
- Xand perhaps some other things.
- XThey have extensive type and range checking
- Xthat produces diagnostic error messages,
- Xso warnings of obviously wrong options will not be discussed here.
- XIn general, options that imply the use of others
- Xwork the way they should; if the page size is set,
- Xthen pagination is automatically assumed.
- XSome combinations of options give impressive, even artistic, effects.
- XMaking a small text file and playing with it is the easiest
- Xway to learn how the options interact.
- X.de OP
- X.TP
- X.B -\\$1 \\$2
- X..
- X*/
- X
- X Boole Breaklines = FALSE; /*MANUAL.OP b
- XBreak all lines of text.
- XThat is, don't even-out lines by filling.
- XBy default, text lines are filled.
- X*/
- X
- X char *Breakchars = NULL; /*MANUAL.OP B breakchars
- XChange the set of characters that cause line breaks at the start of lines to
- X.I breakchars.
- XBy default, any characters but letters and numbers cause a break.
- XA good choice for break characters might be "*-+" and TABS
- Xthat might be used for lists.
- X*/
- X
- X Boole Center = FALSE; /*MANUAL.OP c
- XCenter all lines of text.
- XThis option stops all filling of text.
- X*/
- X
- X Boole Delspace = FALSE; /*MANUAL.OP d
- XDelete white space at the beginning and end of lines.
- XThis option is useful to help un-format text to be re-formatted.
- X*/
- X
- X Boole Delline = FALSE; /*MANUAL.OP D
- XDelete empty input lines.
- XAn input line is empty if it has no characters,
- Xnot even invisible character like tabs or spaces.
- XThis option can be combined with the option to remove white space
- Xto delete visibly blank lines.
- X*/
- X
- X char *Footer = NULL; /*MANUAL.OP f footer
- XSet the page footer to the string
- X.I footer.
- XThis can be any string,
- Xbut if the first character is not a letter or a digit,
- Xbut a punctuation character like /,
- Xthen that character separates the left,
- Xcenter, and right fields of a title.
- XFor example, the title
- X.ce
- X"/ff: fast formatter//1985/"
- Xwould have "ff: fast formatter" as a left justified field
- Xand 1985 as a right justified field on each page.
- XNote that there is no middle field in this example,
- Xbut there could have been, between the two consecutive /'s.
- XThere are two special characters, % and *,
- Xthat respectively are variables for the page number
- Xand the input file name.
- XThe default page footer is blank.
- X*/
- X
- X int Footsize = FOOTSIZE; /*MANUAL.OP F footersize
- XSet the number of blank lines at the bottom of the page.
- XThe footer, if any, is placed in the middle of the space,
- Xwhich by default, is five lines.
- XIf
- X.I footersize
- Xis 0, no footer will be printed.
- X*/
- X
- X char *Header = HEADER; /*MANUAL.OP h header
- XSet the page header.
- XSee the description of three-part titles for the
- X.B -f footer
- Xoption.
- XThe default page header is
- X.ce
- X"|File: *||Page: %|".
- X*/
- X
- X int Headsize = HEADSIZE; /*MANUAL.OP H headersize
- XSee the description of the footer size.
- X*/
- X
- X int Indent = 0; /*MANUAL.OP i indent
- XSet the indentation of the text to
- X.I indent
- Xspaces.
- XNote that this effectively reduces the usable width of the page.
- X*/
- X
- X int Tindent = 0; /*MANUAL.OP I tempindent
- XSet the temporary indent.
- XThis causes filled text found immediately after a break to
- Xbe indented for one line.
- XIt is useful for indenting the first lines of paragraphs.
- XIf
- X.I tempindent
- Xis negative,
- Xthe the temporary indent will be relative to the current
- X.I indent
- Xvalue.
- XIf the
- X.I tempindent
- Xvalue is more negative than the
- X.I indent
- Xvalue is positive,
- X.I ff
- Xwill automatically increase
- X.I indent.
- X*/
- X
- X Boole Justify = FALSE; /*MANUAL.OP j
- XJustify the text.
- XThat is, even the right margin by inserting spaces in the line.
- XOnly filled text can be justified.
- X*/
- X
- X Boole Numlines = FALSE; /*MANUAL.OP n
- XNumber all output lines produced by the input text.
- XLines from multiple line spacing or pagination will not
- Xbe numbered.
- X*/
- X
- X int Numwidth = NUMWIDTH; /*MANUAL.OP N numberwidth
- XSet the width of the line numbers.
- XThe default is to take up 4 spaces.
- XNote that this effectively reduces the usable part of the page.
- X*/
- X
- X Boole Paginate = FALSE; /*MANUAL.OP p
- XPaginate the output.
- XSee the options for page header and footer control.
- X*/
- X
- X int Pagesize = PAGESIZE; /*MANUAL.OP P pagesize
- XSet the number of lines in a page to
- X.I pagesize.
- XBy default, the standard 66 line page is assumed.
- X*/
- X
- X int Spacing = 1; /*MANUAL.OP s spacing
- XSet the line spacing.
- XBy default, text is single spaced (\fIspacing\fR equals 1).
- X*/
- X
- X int Tab[MAXTAB];
- X int Ntabs = 0; /*MANUAL.OP t tab
- XSet individual absolute and relative tab stops.
- XThese values tell the formatter
- Xwhere to put the text (from an unfilled line)
- Xthat follows a tab character.
- XEach tab stop is supplied with its own
- X.B -t
- Xoption; there is no way to bundle them.
- X.I tab
- Xvalues can be integers without a plus sign.
- XThese are \fIabsolute\fR tab settings;
- Xthe tabs go to that position.
- XThe values must increase monotonically.
- XIf a
- X.I tab
- Xvalue is preceded by a plus sign,
- Xthen it is interpreted \fIrelative\fR to the previous tab setting.
- XFor example, a tab setting of 40 followed by one of +20
- Xwill set the second tab stop to 60.
- X*/
- X
- X int Alltabs = 0; /*MANUAL.OP T tabs
- XSet tab stops to every
- X.I tabs
- Xspaces.
- XIt is useful to get equally spaced tabs.
- XThis option cannot be used with the other tab setting option.
- X*/
- X
- X Boole Uppercase = FALSE; /*MANUAL.OP u
- XPrint All Input Text As Initial Upper-Case Titles,
- XLike This Sentence.
- XThis option goes well with the one for centering lines.
- X*/
- X
- X /*MANUAL.OP U
- XPrint a usage summary of all the options and stop.
- X*/
- X
- X int Width = WIDTH; /*MANUAL.OP w width
- XSet the page width.
- XBy default, the page width is 72 characters.
- XNote that the usable line length is sometimes less
- Xthan the page width.
- XIf line numbering or indentation is requested,
- Xthese subtract from the line length.
- X*/
- X
- X/*MANUAL.SH EXAMPLES
- XSome of these examples can make shell scripts or aliases.
- X.nf
- X.ta .5i
- X.sp
- XCentered Titles: title
- X ff -dcu $*
- XDouble Spaced Unfilled Paginated indented (for editing): draft
- X ff -s 2 -b -p -f "`date`" -i 8 $*
- XProgram Listing: cpr
- X H="@ Dir: `pwd`@@File: *@"
- X F="@ $NAME@`date`@Page %@"
- X ff -b -N 8 -H 3 -h "$H" -F 3 -f "$F" -T 4 -w 79 -i 2 $*
- XReformat Paragraphed Text: nr
- X ff -jd -I 5 -i 10 -w 65 -B "TAB SP'*.@" $*
- X.fi
- X*/
- X/*MANUAL.SH DIAGNOSTICS
- XSome options are incompatible with others.
- XFor example, centered text cannot be right-justified.
- X.I ff
- Xwill not allow inconsistent combinations of options.
- X*/
- X/*MANUAL.SH "SEE ALSO"
- Xfmt(1), nroff(1), scribe(1w)
- X*/
- X/*MANUAL.SH AUTHOR
- XGary Perlman (with help from many students)
- X*/
- X/*MANUAL.SH STATUS
- XPretty well tested.
- X*/
- X
- X/* Macro Functions */
- X/*MACRO isendsent: is the character one that ends a sentence? */
- X#define isendsent(c) ((c) == '.' || (c) == '?' || (c) == '!')
- X
- X/*MACRO justchar: add char to a buffer that will later be flushed */
- X#define justchar(c) (Justbuf[Justpos++] = (c))
- X
- X/*MACRO fillchar: save to justify if necessary, else output */
- X#define fillchar(c) \
- X { \
- X if (Justify == TRUE) justchar (c); \
- X else putc (c, stdout); \
- X }
- X
- X/*FUNCTION main: loop through files in classic UNIX filter style */
- Xmain (argc, argv)
- Xint argc; /* argument count */
- Xchar **argv; /* argument vector */
- X {
- X Status ff (); /* ff (file, ioptr) will filter files */
- X Status status; /* return status of filter () */
- X int firstfile; /* first file name index returned by initial */
- X
- X firstfile = initial (argc, argv);
- X status = filter (argc, argv, firstfile, ff);
- X exit (status);
- X }
- X
- X/*FUNCTION setint: check type, convert string, and set integer option */
- XStatus
- Xsetint (flag, value, var, min, max)
- Xint flag; /* the single character option name */
- Xchar *value; /* the candidate value, in string format */
- Xint *var; /* ptr to variable to stuff in answer */
- Xint min; /* minimum allowed value */
- Xint max; /* maximum allowed value */
- X {
- X int tmpvar;
- X if (number (value) == 1) /* number returns 1 for integers, 2 for reals */
- X {
- X tmpvar = atoi (value);
- X if (tmpvar >= min && tmpvar <= max)
- X {
- X *var = tmpvar;
- X return (SUCCESS);
- X }
- X fprintf (stderr, "%s: -%c option value must be between %d and %d\n",
- X Argv0, flag, min, max);
- X return (FAILURE);
- X }
- X fprintf (stderr, "%s: -%c option requires an integer value\n", Argv0, flag);
- X return (FAILURE);
- X }
- X
- X/*FUNCTION usage: print help menu */
- Xvoid
- Xusage (ioptr)
- XFILE *ioptr;
- X {
- X fprintf (ioptr, "%s: fast text formatter options:\n", Argv0);
- X fprintf (ioptr, "-b break all lines of text--do no filling\n");
- X fprintf (ioptr, "-B s line break characters\n");
- X fprintf (ioptr, "-c center all text lines\n");
- X fprintf (ioptr, "-d delete blank space around input lines\n");
- X fprintf (ioptr, "-D delete blank input lines\n");
- X fprintf (ioptr, "-f s page footer three-part title\n");
- X fprintf (ioptr, "-F i page footer size (%d lines)\n", Footsize);
- X fprintf (ioptr, "-h s page header three-part title (%s)\n", Header);
- X fprintf (ioptr, "-H i page header size (%d lines)\n", Headsize);
- X fprintf (ioptr, "-i i text indentation (%d spaces)\n", Indent);
- X fprintf (ioptr, "-I i indent after line breaks (%d spaces)\n", Tindent);
- X fprintf (ioptr, "-j justify the right margin of the text\n");
- X fprintf (ioptr, "-n number output text lines\n");
- X fprintf (ioptr, "-N i width of line numbers (%d spaces)\n", Numwidth);
- X fprintf (ioptr, "-p paginate output\n");
- X fprintf (ioptr, "-P i page size (%d lines)\n", Pagesize);
- X fprintf (ioptr, "-s i line spacing (%d line)\n", Spacing);
- X fprintf (ioptr, "-t i absolute or relative tab stop\n");
- X fprintf (ioptr, "-T i uniform tab stops\n");
- X fprintf (ioptr, "-u show text with upper-case initial letters\n");
- X fprintf (ioptr, "-U print long usage synopsis for this command\n");
- X fprintf (ioptr, "-w i page line width (%d spaces)\n", Width);
- X }
- X
- X/*FUNCTION initial: set options */
- Xint
- Xinitial (argc, argv) char **argv;
- X {
- X extern char *optarg; /* string value to option set by getopt */
- X extern int optind; /* will be index of first command operand */
- X int errcount = 0; /* count of number of errors */
- X int flag; /* options flag names read in here */
- X char *optstring = /* Boolean flags and integer options with : */
- X "bcdDjnpuUB:f:F:h:H:i:I:N:P:s:t:T:w:";
- X
- X Argv0 = argv[0];
- X while ((flag = getopt (argc, argv, optstring)) != EOF)
- X switch (flag)
- X {
- X default:
- X errcount++;
- X break;
- X
- X case 'b':
- X Breaklines = TRUE;
- X break;
- X
- X case 'B':
- X Breakchars = optarg;
- X break;
- X
- X case 'c':
- X Center = TRUE;
- X Breaklines = TRUE;
- X break;
- X
- X case 'd':
- X Delspace = TRUE;
- X break;
- X
- X case 'D':
- X Delline = TRUE;
- X break;
- X
- X case 'f':
- X Footer = optarg;
- X Paginate = TRUE;
- X break;
- X
- X case 'F':
- X if (setint (flag, optarg, &Footsize, 0, MAXLINES) == FAILURE)
- X errcount++;
- X Paginate = TRUE;
- X break;
- X
- X case 'h':
- X Header = optarg;
- X Paginate = TRUE;
- X break;
- X
- X case 'H':
- X if (setint (flag, optarg, &Headsize, 0, MAXLINES) == FAILURE)
- X errcount++;
- X Paginate = TRUE;
- X break;
- X
- X case 'i':
- X if (setint (flag, optarg, &Indent, 0, MAXLEN) == FAILURE)
- X errcount++;
- X break;
- X
- X case 'I':
- X if (setint (flag, optarg, &Tindent, -MAXLEN, MAXLEN) == FAILURE)
- X errcount++;
- X break;
- X
- X case 'j':
- X Justify = TRUE;
- X break;
- X
- X case 'N':
- X if (setint (flag, optarg, &Numwidth, 1, MAXLEN) == FAILURE)
- X errcount++;
- X /* FALLTHROUGH */
- X
- X case 'n':
- X Numlines = TRUE;
- X break;
- X
- X case 'P':
- X if (setint (flag, optarg, &Pagesize, 1, MAXLINES) == FAILURE)
- X errcount++;
- X /* FALLTHROUGH */
- X
- X case 'p':
- X Paginate = TRUE;
- X break;
- X
- X case 's':
- X if (setint (flag, optarg, &Spacing, 1, MAXLINES) == FAILURE)
- X errcount++;
- X break;
- X
- X case 't':
- X if (Ntabs >= MAXTAB)
- X {
- X fprintf (stderr, "%s: at most %d -%c options allowed\n",
- X Argv0, MAXTAB, flag);
- X errcount++;
- X }
- X else if (setint (flag, optarg, &Tab[Ntabs], 0, MAXLEN) == FAILURE)
- X errcount++;
- X else if (Ntabs > 0)
- X {
- X if (*optarg == '+')
- X Tab[Ntabs] += Tab[Ntabs-1];
- X else if (Tab[Ntabs] <= Tab[Ntabs-1])
- X {
- X fprintf (stderr, "%s: -%c values must increase\n",
- X Argv0, flag);
- X errcount++;
- X }
- X }
- X if (Tab[Ntabs] >= MAXLEN)
- X {
- X fprintf (stderr, "%s: -%c values must be < %d\n",
- X Argv0, flag, MAXLEN);
- X errcount++;
- X }
- X Ntabs++;
- X break;
- X
- X case 'T':
- X if (setint (flag, optarg, &Alltabs, 1, MAXLEN) == FAILURE)
- X errcount++;
- X break;
- X
- X case 'u':
- X Uppercase = TRUE;
- X break;
- X
- X case 'U':
- X usage (stdout);
- X exit (0);
- X
- X case 'w':
- X if (setint (flag, optarg, &Width, 1, MAXLEN) == FAILURE)
- X errcount++;
- X break;
- X }
- X
- X /* Now check validity of option settings */
- X if (Tindent < 0 && Indent < (-Tindent))
- X Indent = (-Tindent);
- X if (Ntabs > 0 && Alltabs > 0)
- X {
- X fprintf (stderr, "%s: can't set individual and all tabs\n", Argv0);
- X errcount++;
- X }
- X if (Center == TRUE && Justify == TRUE)
- X {
- X fprintf (stderr, "%s: centering and justifying incompatible\n", Argv0);
- X errcount++;
- X }
- X else if (Breaklines == TRUE && Justify == TRUE)
- X {
- X fprintf (stderr, "%s: breaking and justifying incompatible\n", Argv0);
- X errcount++;
- X }
- X if (Ntabs > 0 && Center == TRUE)
- X {
- X fprintf (stderr,"%s: centering and setting tabs incompatible\n", Argv0);
- X errcount++;
- X }
- X if ((Ntabs > 0 || Alltabs > 0) && (Justify == TRUE))
- X {
- X fprintf (stderr, "%s: tabstops and justifying incompatible\n", Argv0);
- X errcount++;
- X }
- X
- X /* Print an error message and exit or return index to first file name */
- X if (errcount > 0)
- X {
- X fprintf (stderr, "Usage: %s [options] [-] [files]\n", Argv0);
- X exit (FAILURE);
- X }
- X return (optind);
- X }
- X
- X/*FUNCTION repeat: repeat a character some number of times */
- Xvoid
- Xrepeat (c, n)
- Xint c; /* character to print */
- Xint n; /* number of times to print c */
- X {
- X while (n-- > 0)
- X putc (c, stdout);
- X }
- X
- X/*FUNCTION dotab: expand tabs to spaces to tab stops, returns static buffer */
- X/*ALGORITHM
- X if all tabs are set to the same value (Alltabs > 0)
- X then advance on a tab to the next tab stop
- X else if there are individual tabs set (Ntabs > tabno)
- X then advance (possibly retreat!) to next set tab
- X else just treat the tab like a space character
- X*/
- Xchar *
- Xdotab (line)
- Xregister char *line;
- X {
- X static char outline[MAXLEN]; /* new line will be built here */
- X register char *lptr; /* pointer to current position in outline */
- X register char *nextptr; /* position of next tab stop */
- X int tabno = 0; /* how many tabs have been processed */
- X
- X for (lptr = outline; *line != EOS && *line != EOL; line++)
- X {
- X if (*line == TAB)
- X {
- X if (Alltabs > 0)
- X nextptr = lptr + Alltabs - ((lptr - outline) % Alltabs);
- X else if (Ntabs > tabno) /* move to next set tab */
- X nextptr = outline + Tab[tabno++];
- X else
- X nextptr = lptr + 1;
- X if (lptr < nextptr)
- X do {
- X *lptr++ = SP;
- X } while (lptr < nextptr);
- X else lptr = nextptr;
- X }
- X else
- X *lptr++ = *line;
- X
- X /* check for line overflow */
- X if (lptr >= (outline + MAXLEN))
- X return (NULL);
- X }
- X
- X /* end the expanded tab string and return */
- X *lptr = EOS;
- X return (outline);
- X }
- X
- X/*FUNCTION dojustify: even the right margin for all lines */
- X/*ALGORITHM
- X directly output any indenting spaces (this is not expanded)
- X trim trailing spaces (don't want to pad at end)
- X count number of spaces inside line (where extra spaces will be inserted)
- X distribute the extra spaces needed among the spaces there
- X Note: if we are not filling (e.g., last line of output before a break)
- X then we do not justfy the right margin.
- X*/
- Xvoid
- Xdojustify ()
- X {
- X register char *line; /* will point to first non-space char on line */
- X int width; /* width of line to pad - #'s and indent */
- X register char *lptr; /* zips through the line */
- X int pad; /* will need to pad with this many spaces */
- X int spaces = 0; /* will be number of embedded spaces in line */
- X register int i; /* used inside inner loop */
- X int n = 0;
- X
- X if (Justpos == 0) /* nothing to justify, so bail out */
- X return;
- X
- X /* strip spaces from end of line and end with EOS */
- X for (lptr = Justbuf+Justpos; lptr>Justbuf && isspace(lptr[-1]); lptr--);
- X *lptr = EOS;
- X
- X width = Width - (Numlines == TRUE ? Numwidth : 0);
- X pad = width - (lptr - Justbuf);
- X
- X for (line = Justbuf; *line == SP; line++)
- X putc (*line, stdout);
- X
- X if (Filling == TRUE && pad > 0) /* might not fill last line of output */
- X for (lptr = line; *lptr != EOS; lptr++)
- X if (*lptr == SP)
- X spaces++;
- X
- X if (spaces > 0) /* we have places to insert spaces */
- X {
- X for (lptr = line; *lptr != EOS; lptr++)
- X {
- X if (*lptr == SP)
- X for (i = 0; i < pad; i++)
- X if (++n == spaces)
- X {
- X putc (SP, stdout);
- X n = 0;
- X }
- X putc (*lptr, stdout);
- X }
- X }
- X else /* just output the line */
- X for (lptr = line; *lptr != EOS; lptr++)
- X putc (*lptr, stdout);
- X
- X Justpos = 0; /* reset buffer position for next line */
- X }
- X
- X/*FUNCTION println: print lines while watching for page boundaries */
- Xvoid
- Xprintln (count)
- Xint count; /* how many lines to print (== Spacing) */
- X {
- X Curpos = 0;
- X while (count-- > 0)
- X {
- X putc (EOL, stdout);
- X Pageline++;
- X if (Paginate == TRUE && ((Pagesize - Pageline) == Footsize))
- X {
- X endpage (TRUE);
- X return;
- X }
- X }
- X }
- X
- X/*FUNCTION beginline: do any needed justification, paginate if requested, */
- X/* handle line numbering, temp and regular indents based on prev. filling */
- Xvoid
- Xbeginline (filling)
- XBoole filling; /* are we filling now? */
- X {
- X int count;
- X Boole newfill = (Filling == FALSE && filling == TRUE);
- X
- X Filling = filling;
- X if (Justify == TRUE)
- X dojustify ();
- X Outline++;
- X Curpos = 0;
- X
- X if (Paginate == TRUE && Pageline == 0)
- X beginpage ();
- X else if (Outline > 1)
- X println (Spacing);
- X
- X if (Numlines == TRUE)
- X {
- X char *ptr = itoa (Outline, Numwidth - 1);
- X Curpos += Numwidth;
- X while (*ptr)
- X putc (*ptr++, stdout);
- X putc (SP, stdout);
- X }
- X
- X count = Indent;
- X if (newfill == TRUE)
- X count += Tindent;
- X Curpos += count;
- X
- X if (Justify == TRUE)
- X while (count-- > 0)
- X justchar (SP);
- X else
- X repeat (SP, count);
- X }
- X
- X/*FUNCTION itoa: integer to ascii conversion */
- Xchar *
- Xitoa (n, pad)
- Xregister int n; /* the integer to be printed as a string */
- Xint pad; /* amount of space to pad number to */
- X {
- X static char numbuf[MAXLEN]; /* answer built in here */
- X register char *nptr; /* will be pointer to beginning of number */
- X Boole negflg = FALSE; /* is the number a negative value? */
- X
- X /* static numbuf is initialized to 0's, so numbuf[MAXLEN-1] == EOS */
- X if (n == 0)
- X {
- X nptr = &numbuf[MAXLEN-1];
- X *--nptr = '0';
- X }
- X else
- X {
- X if (n < 0)
- X {
- X n = (-n);
- X negflg = TRUE;
- X }
- X for (nptr = &numbuf[MAXLEN-1]; n != 0; n /= 10)
- X *--nptr = (n % 10) + '0';
- X if (negflg == TRUE)
- X *--nptr = '-';
- X }
- X
- X while (pad > numbuf+MAXLEN-1-nptr)
- X *--nptr = SP;
- X
- X return (nptr);
- X }
- X
- X/*FUNCTION expand: insert file/page for characters in field of 3part title */
- Xchar *
- Xexpand (title, page, file)
- Xregister char *title; /* the title to be expanded */
- Xint page; /* the current page number */
- Xchar *file; /* the name of the current file */
- X {
- X static char answer[MAXLEN]; /* title expanded into this buffer */
- X register char *aptr; /* pointer to answer buf */
- X register char *ptr; /* generic string handling pointer */
- X
- X for (aptr = answer; *title != EOS; title++)
- X switch (*title)
- X {
- X default:
- X *aptr++ = *title;
- X break;
- X
- X case PAGENUM:
- X ptr = itoa (page, 0);
- X while (*ptr != EOS)
- X *aptr++ = *ptr++;
- X break;
- X
- X case FILENAME:
- X for (ptr = file; *ptr != EOS; ptr++)
- X *aptr++ = *ptr;
- X break;
- X }
- X *aptr = EOS;
- X return (answer);
- X }
- X
- X/*FUNCTION threepart: 3-part title with left/center/right justified fields */
- X/* any punctuation character can be the title delimiter: see nroff(1) */
- Xchar *
- Xthreepart (title, page, file, width)
- Xchar *title; /* the three part title */
- Xint page; /* the current page number */
- Xchar *file; /* the current file name */
- Xint width; /* the current page width */
- X {
- X static char answer[MAXLEN]; /* answer stuffed in here */
- X register char *aptr; /* pointer to answer buffer */
- X int delim; /* title delimiter character */
- X
- X title = expand (title, page, file);
- X if (!ispunct (*title))
- X return (title);
- X for (aptr = answer; aptr < answer + width; aptr++)
- X *aptr = SP;
- X aptr = answer;
- X delim = *title++;
- X while (*title != EOS && *title != delim)
- X *aptr++ = *title++;
- X if (*title++ != EOS) /* now do center */
- X {
- X char *lptr = title;
- X while (*lptr != EOS && *lptr != delim)
- X lptr++;
- X aptr = answer + (width - (lptr - title)) / 2;
- X if (aptr >= answer)
- X while (*title != EOS && *title != delim)
- X *aptr++ = *title++;
- X else
- X while (*title != EOS && *title != delim)
- X title++;
- X if (*title++ != EOS) /* now do left part */
- X {
- X char *eptr = title;
- X while (*eptr != EOS && *eptr != delim)
- X eptr++;
- X eptr--;
- X aptr = answer + width - 1;
- X while (eptr >= title)
- X *aptr-- = *eptr--;
- X }
- X }
- X answer[width] = EOS;
- X return (answer);
- X }
- X
- X/*FUNCTION beginpage: handle page header */
- Xvoid
- Xbeginpage ()
- X {
- X Pagenum++;
- X if (Paginate == TRUE && Headsize > 0)
- X {
- X int space1 = Headsize / 2;
- X int space2 = Headsize - space1;
- X char *optr = threepart (Header, Pagenum, Filename, Width);
- X
- X repeat (EOL, space1);
- X while (*optr != EOS)
- X putc (*optr++, stdout);
- X repeat (EOL, space2);
- X Pageline = Headsize;
- X }
- X }
- X
- X/*FUNCTION endpage: break filling (output justified text) print footer */
- X/* begin a new page if there is more */
- Xvoid
- Xendpage (more)
- XBoole more;
- X {
- X if (Justify == TRUE)
- X dojustify ();
- X
- X if (Paginate == TRUE)
- X {
- X int space1 = Footsize / 2;
- X int space2 = Footsize - space1;
- X char *optr = threepart (Footer, Pagenum, Filename, Width);
- X
- X repeat (EOL, Pagesize - Pageline - space2);
- X while (*optr != EOS)
- X putc (*optr++, stdout);
- X repeat (EOL, space2);
- X Pageline = 0;
- X }
- X else if (Curpos > 0 || Indent > 0 || Numlines == TRUE)
- X putc (EOL, stdout);
- X
- X if (more == TRUE)
- X beginpage ();
- X }
- X
- X/*FUNCTION preprocess: trim space, find blank lines, do titling */
- Xchar *
- Xpreprocess (line)
- Xregister char *line;
- X {
- X register char *lptr;
- X if (Paginate == TRUE && *line == FF)
- X {
- X line++;
- X endpage (TRUE);
- X }
- X if (Delspace == TRUE) /* delete blank space */
- X {
- X while (isspace (*line))
- X line++;
- X for (lptr = line; *lptr != EOS; lptr++);
- X while (lptr > line && isspace (*(lptr-1)))
- X lptr--;
- X *lptr = EOS;
- X }
- X if (Delline == TRUE && (*line == EOL || *line == EOS))
- X return (NULL);
- X if (Uppercase == TRUE)
- X {
- X Boole newword; /* are we at the start of a new word? */
- X for (lptr = line, newword = TRUE; *lptr != EOS; lptr++)
- X {
- X if (newword && islower (*lptr))
- X *lptr = toupper (*lptr);
- X newword = !isalnum (*lptr);
- X }
- X }
- X return (line);
- X }
- X
- X/*FUNCTION dobreak: process broken line & return success status */
- XStatus
- Xdobreak (lptr)
- Xregister char *lptr; /* line to print out */
- X {
- X /* break: do tabs, or centering, and then dump the line out */
- X beginline (FALSE);
- X if (Alltabs > 0 || Ntabs > 0) /* some tabs have been set */
- X {
- X if ((lptr = dotab (lptr)) == NULL)
- X {
- X fprintf (stderr, "%s: malformed tab in %s at line %d\n",
- X Argv0, Filename, Outline);
- X return (FAILURE);
- X }
- X }
- X else if (Center == TRUE && *lptr != EOS && *lptr != EOL)
- X repeat (SP, (Width - strlen (lptr)) / 2);
- X while (*lptr != EOS && *lptr != EOL)
- X putc (*lptr++, stdout);
- X Curpos = Width; /* signal end of line */
- X return (SUCCESS);
- X }
- X
- X/*FUNCTION dofill: do line filling */
- Xvoid
- Xdofill (lptr)
- Xregister char *lptr;
- X {
- X register char *eptr; /* pointer to end of filled words */
- X register int wordlen; /* length of words */
- X
- X while (isspace (*lptr))
- X lptr++;
- X while (*lptr != EOS) /* fill text by picking up word by word */
- X {
- X eptr = lptr;
- X while (*eptr != EOS && !isspace (*eptr))
- X eptr++;
- X wordlen = eptr - lptr;
- X if ((Outline == 0) || (Curpos + wordlen) >= Width)
- X beginline (TRUE);
- X else if (Curpos < Width) /* space before word */
- X {
- X fillchar (SP);
- X Curpos++;
- X }
- X for (Curpos += wordlen; lptr < eptr; lptr++)
- X fillchar (*lptr);
- X while (isspace (*lptr))
- X lptr++;
- X
- X /* extra space at sentence ends (.?!) */
- X if ((Curpos < Width) && isendsent (*(eptr-1)) && wordlen > 2)
- X {
- X fillchar (SP);
- X Curpos++;
- X }
- X }
- X }
- X
- X/*FUNCTION ff: main formatting routine */
- X/*
- X initializes for each new file, reads lines, trims space and blank lines
- X switches between filling and non filling based on breakchars
- X*/
- XStatus
- Xff (file, ioptr)
- Xchar *file; /* file name */
- XFILE *ioptr; /* opened input pointer */
- X {
- X char line[BUFSIZ]; /* lines read in here */
- X register char *lptr; /* pointer used to go through line */
- X Status status = SUCCESS;
- X
- X Outline = Pagenum = Pageline = Curpos = 0;
- X Filename = file;
- X Filling = FALSE;
- X
- X while (fgets (lptr = line, sizeof (line), ioptr))
- X {
- X if ((lptr = preprocess (lptr)) == NULL)
- X continue;
- X
- X if ((Breaklines == TRUE)
- X || (*lptr == EOL)
- X || (Breakchars ? index (Breakchars, *lptr) != NULL : !isalnum (*lptr)))
- X {
- X if (dobreak (lptr) == FAILURE)
- X return (FAILURE);
- X }
- X
- X else
- X
- X dofill (lptr);
- X }
- X
- X Filling = FALSE;
- X endpage (FALSE);
- X return (status);
- X }
- SHAR_EOF
- if test 29326 -ne "`wc -c < 'ff.c'`"
- then
- echo shar: "error transmitting 'ff.c'" '(should have been 29326 characters)'
- fi
- fi
- exit 0
- # End of shell archive
-
-